package com.bioscript.standalone.dataStructures;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Range {

	private int lowerLimit = 0;
	private int upperLimit = 0;
	private String metadata = null;
	private String name = null;
	private boolean orientation = true;
	
	public static Range getNewInstance(String str)
	{
		String[] params = str.split("\t");
		if (params.length == 3)
		{
			return new Range(Integer.parseInt(params[1]), Integer.parseInt(params[2]), params[0]);
		}
		else if (params.length == 2)
		{
			return new Range(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
		}
		else
		{
			return new Range(Integer.parseInt(params[1]), Integer.parseInt(params[2]), params[0]);
		}
	}
	
	public boolean isReverse_new()
	{
		return !orientation;
	}
	
	public void setReverse()
	{
		orientation = false;
	}
	
	public String getName()
	{
		return name;
	}
	
	public int getLength() 
	{
		return Math.abs(upperLimit - lowerLimit) + 1;
	}
	
	public int getLength(int referenceSize)
	{
		int temp_upperLimt = upperLimit;
		int temp_lowerLimt = lowerLimit;
//		if (upperLimit < 0)
//		{
//			temp_upperLimt = referenceSize + temp_upperLimt;
//		}
//		if (lowerLimit < 0)
//		{
//			temp_lowerLimt = referenceSize + temp_lowerLimt;
//		}
//		if (lowerLimit < referenceSize && lowerLimit > upperLimit)
//		{
//			return
//		}
		return temp_upperLimt - temp_lowerLimt ;
	}
	
	public Range (String name)
	{
		this.name = name;
	}
	
	public Range (int lowerLimit, int upperLimit, String name)
	{
		this.lowerLimit = lowerLimit;
		this.upperLimit = upperLimit;
		this.name = name;
	}
	
	public Range (int lowerLimit, int upperLimit)
	{
		this.lowerLimit = lowerLimit;
		this.upperLimit = upperLimit;
	}
	
	public Range setUpperLimit(int upperLimit)
	{
		this.upperLimit = upperLimit;
		return this;
	}
	
	public Range setLowerLimit(int lowerLimit)
	{
		this.lowerLimit = lowerLimit;
		return this;
	}
	
	public Range setMetadata(String metadata)
	{
		this.metadata = metadata;
		return this;
	}
	
	public boolean contains(Range r)
	{
		if (lowerLimit <= r.getLowerLimit() && upperLimit > r.getUpperLimit())
			return true;
		else if (lowerLimit < r.getLowerLimit() && upperLimit >= r.getUpperLimit())
			return true;
		else 
			return false;
	}
	
	public boolean overLap(Range r)
	{
		return r.containsPosition(lowerLimit) ||
		r.containsPosition(upperLimit) ||
		containsPosition(r.getLowerLimit());
	}
	
	public boolean containsPosition(int pos)
	{
		if (lowerLimit > upperLimit)
		{
			if (lowerLimit < pos || pos < upperLimit)
			{
				return true;
			}
		}
		else
		{
			if (lowerLimit < pos && pos < upperLimit)
			{
				return true;
			}
		}
		return false;
	}
	public boolean exclusive(Range r)
	{
//		if ((lowerLimit < r.getLowerLimit() && r.getLowerLimit() < upperLimit)
//				|| (lowerLimit < r.getUpperLimit() && r.getUpperLimit() < upperLimit))
//			return false;
//		else return true;
		
		
		if ((lowerLimit < r.getLowerLimit() && r.getLowerLimit() > upperLimit)
				|| (lowerLimit > r.getUpperLimit() && r.getUpperLimit() < upperLimit))
			return true;
		else return false;
	}
	
	
	public boolean exclusive_new(Range r)
	{
		 	
		if (isReverse_new())
		{
			
		}
		if (r.isReverse_new())
		{
			
		}
		if ((lowerLimit < r.getLowerLimit() && r.getLowerLimit() > upperLimit)
				|| (lowerLimit > r.getUpperLimit() && r.getUpperLimit() < upperLimit))
			return true;
		else return false;
	}
	
	public int getUpperLimit()
	{
		return upperLimit;
	}
	
	public int getLowerLimit()
	{
		return lowerLimit;
	}
	
	public String getMetadata()
	{
		return metadata;
	}
	
	public boolean isReverse()
	{
		return lowerLimit > upperLimit;
	}
	
	public String toString()
	{
		StringBuffer buffer = new StringBuffer();
		if (name != null)
		{
			buffer.append(name + "\t");
		}
		buffer.append(lowerLimit + "\t" + upperLimit);
		return buffer.toString();
	}
	
	public Element toXML(Document doc)
	{
		try
		{
			Element con = doc.createElement("gap");
			con.setAttribute("start", String.valueOf(getLowerLimit()));
			con.setAttribute("end", String.valueOf(getUpperLimit()));
			con.setAttribute("name", getName());
//			con.setAttribute("length", String.valueOf(actualRange.getLength()));
			return con;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	public static List<String> getStringList(List<Range> lst)
	{
		List<String> strs = new ArrayList<String>();
		for(Range contig : lst)
		{
			strs.add(contig.toString());
		}
		return strs;
	}
	
	public static List<Range> getRangeList(List<String> lst)
	{
		List<Range> r = new ArrayList<Range>();
		for(String contig : lst)
		{
			r.add(Range.getNewInstance(contig));
		}
		return r;
	}
}
